﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;

namespace Manyor.Net
{
    /// <summary>
    /// 文件传送端
    /// </summary>
    public class ClientFileTransfer:ICommand
    {
        #region -- Event --
        /// <summary>
        /// 文件传输开始
        /// </summary>
        public event EventHandler OnFileBeginTrans;
        /// <summary>
        /// 文件传输结束
        /// </summary>
        public event EventHandler OnFileTransComplate;
        /// <summary>
        /// 传输进度改变
        /// </summary>
        public event EventHandler OnFileTransProcessChanged;
        /// <summary>
        /// 发生错误
        /// </summary>
        public event EventHandler OnError;
        #endregion 

        /// <summary>
        /// 发送委托
        /// </summary>
        private Action<byte[]> _sendAction;
        /// <summary>
        /// 文件流
        /// </summary>
        private FileStream fs;
        /// <summary>
        /// 文件保存路径
        /// </summary>
        private string FilePath { get; set; }

        /// <summary>
        /// 只是当前任务是否正在进行
        /// </summary>
        public bool IsBusy { get; set; }
        /// <summary>
        /// 继续传输锁
        /// </summary>
        private bool ContinueTranfserLock;
        /// <summary>
        /// 发送线程
        /// </summary>
        private Thread TransferThread;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="sendAction">发送消息的代理</param>
        public ClientFileTransfer(Action<byte[]> sendAction)
        {
            //ContinueTranfserLock = new object();
            _sendAction = sendAction;
            TransferThread = new Thread(new ThreadStart(TransferThreadMethod));
            TransferThread.IsBackground = true;
            TransferThread.Start();            
        }
       
        /// <summary>
        /// 准备开始传输文件
        /// </summary>
        /// <param name="filePath"></param>
        public void ReadyTransferFile(string filePath)
        {
            ContinueTranfserLock = true;
            FilePath = filePath;
            ///发送文件名
            byte[] bytesFileName=System.Text.Encoding.UTF8.GetBytes(Path.GetFileName(filePath));
            //发送文件传输开始标志位           
            SocketHeader sh = new SocketHeader() 
            {
                CommandField = CommandCode.COMMAND_TRANSFER,
                StatuField = CommandCode.CONNECT_TRANSFER_READY
            };            
            _sendAction(ByteUtility.CombineBytes(ByteUtility.SocketHeader(sh), bytesFileName));
            //传输开始
            if (OnFileBeginTrans != null)
                OnFileBeginTrans(null, null);
        }
        /// <summary>
        /// 传输线程
        /// </summary>
        public void TransferThreadMethod()
        {
            while (true)
            {
                if (!IsBusy)
                {
                    Thread.Sleep(200);
                    continue;
                }
                #region
                using (FileStream fs = new FileStream(FilePath, FileMode.Open))
                {                    
                    int contentLength = NetConfig.CONTENT_SIZE;
                    //计算所需要传输的次数
                    int sendTimes = (int)fs.Length / contentLength;
                    if (fs.Length > sendTimes * contentLength)
                    {
                        sendTimes++;
                    }
                    //分次发送
                    for (int i = 0; i < sendTimes; i++)
                    {                       
                        lock (this)
                        {
                            if (!ContinueTranfserLock)
                            {
                                Thread.Sleep(2);
                                i--;
                                continue;
                            }
                            int timeLength = (int)((fs.Length - i * contentLength) / contentLength >= 1 ? contentLength : fs.Length - i * contentLength);
                            byte[] bytes = new byte[NetConfig.HEADER_SIZE + timeLength];
                            SocketHeader sh = new SocketHeader()
                            {
                                CommandField = CommandCode.COMMAND_TRANSFER,
                                StatuField = CommandCode.CONNECT_TRANSFER_DOING,
                                ExtField = (int)((fs.Length / (1024.0 * 1024.0)) * 100)       //单位,MB
                            };
                            //传送完毕，发送标识
                            if (i == sendTimes - 1)
                            {
                                sh.StatuField = CommandCode.CONNECT_TRANFSER_FINISH;
                                //传输完毕
                                if (OnFileTransComplate != null)
                                {
                                    OnFileTransComplate(null, null);
                                }
                            }
                            //加入Socket头
                            ByteUtility.PushSockHeaderToBytes(sh, bytes);
                            fs.Read(bytes, NetConfig.HEADER_SIZE, timeLength);
                            _sendAction(bytes);

                            //传输进度改变
                            if (OnFileTransProcessChanged != null)
                                OnFileTransProcessChanged(this, new FileEventArgs()
                                {
                                    FileName = Path.GetFileName(FilePath),
                                    TransferedPercent = i * 100 / sendTimes
                                });                           
                            ContinueTranfserLock = false;                            
                        }
                    }
                    IsBusy = false;
                }
                #endregion
            }
        }

        /// <summary>
        /// 开始传送文件
        /// </summary>
        protected void BeginTransferFile()
        {
            if (!System.IO.File.Exists(FilePath))
            {
                //throw new FileNotFoundException();
                if (OnError != null)
                {
                    OnError("文件不存在！", null);
                }
                return;
            }
            //开始线程
            IsBusy = true;            
        }

        /// <summary>
        /// 继续传输
        /// </summary>
        protected void ContinueTransfer()
        {
            lock (this)
            {
                ContinueTranfserLock = true;
            }
        }
        #region ICommand 成员
       
        /// <summary>
        /// 接受指令
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="length"></param>
        public void ExecuteCommand(byte[] bytes, int length)
        {
            SocketHeader sh = ByteUtility.ConvertHeader(bytes);
            //可以开始传输文件
            if (sh.StatuField == CommandCode.CONNECT_TRANSFER_BEGIN)
            {
                BeginTransferFile();
            }
            //继续发送下一个数据包
            else if (sh.StatuField == CommandCode.CONNECT_TRANSFER_NEXT)
            {
                ContinueTransfer();
            }
        }

        ~ClientFileTransfer()
        {
            if (TransferThread.IsAlive)
            {
                TransferThread.Abort();
            }
        }
        #endregion
    }
}
